<?php

namespace App\Console\Commands\Fix;

use App\Common\Libs\Json;
use App\Console\BaseCommand;
use App\Consts\GlobalConst;
use App\Models\IndexArticle;
use App\Models\IndexCollectPackage;
use App\Models\IndexComment;
use App\Models\IndexDynamic;
use App\Models\IndexNote;
use App\Models\IndexSearchCollect;
use App\Models\SysArticle;
use App\Models\SysComment;
use App\Models\SysDynamic;
use App\Models\SysNote;
use App\Models\SysNoteContent;
use App\Models\SysNoteLine;
use App\Models\SysReply;
use App\Models\UserCollect;
use App\Models\UserCollectPackage;
use Illuminate\Database\Query\Builder;

/**
 * 索引表数据修复
 * Class IndexFixCommand
 * @package App\Console\Commands\Fix
 */
class IndexFixCommand extends BaseCommand
{

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fix:index {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'fix index_* table data';

    /**
     * 索引修复 - 文章
     * @return int
     */
    public function article()
    {
        $subMode = $this->_getArticleSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                // get index data
                $data = IndexArticle::getModel()
                    ->where('article_id', $item->article_id)
                    ->where('author_id', $item->author_id)
                    ->first();
                if (empty($data)) {
                    // insert data into table
                    $insert = [
                        'article_id' => $item->article_id,
                        'author_id' => $item->author_id,
                        'spider_original_id' => $item->spider_original_id,
                        'is_deleted' => $item->is_deleted,
                        'is_shield' => $item->is_shield,
                    ];
                    $res = IndexArticle::getModel()->create($insert);
                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_article` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check article_id : {$item->article_id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'article_id');
        return 1;
    }

    /**
     * 索引修复 - 动态
     * @return int
     */
    public function dynamic()
    {
        $subMode = $this->_getDynamicSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                // get index data
                $data = IndexDynamic::getModel()
                    ->where('dynamic_id', $item->dynamic_id)
                    ->first();
                if (empty($data)) {
                    // insert data into table
                    $insert = [
                        'dynamic_id' => $item->dynamic_id,
                        'user_id' => $item->user_id,
                        'target_id' => $item->target_id,
                        'target_type' => $item->target_type,
                        'note_type' => $item->note_type,
                        'type' => $item->type,
                        'is_view' => $item->is_view,
                        'is_deleted' => $item->is_deleted,
                    ];
                    $res = IndexDynamic::getModel()->create($insert);
                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_dynamic` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check dynamic_id : {$item->dynamic_id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'dynamic_id');
        return 1;
    }

    /**
     * 索引修复 - 评论
     * @return int
     */
    public function comments()
    {
        $subMode = $this->_getCommentSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                // get index data
                $data = IndexComment::getModel()
                    ->where('comment_id', $item->comment_id)
                    ->first();
                if (empty($data)) {
                    $reply = SysReply::getSubModel(function (Builder $query) use($item) {
                        $query->where('comment_id', $item->comment_id);
                    })->first();
                    // insert data into table
                    $insert = [
                        'comment_id' => $item->comment_id,
                        'reply_id' => $reply->reply_id ?? 0,
                        'to_reply_id' => $reply->to_reply_id ?? 0,
                        'target_id' => $item->target_id,
                        'target_type' => $item->target_type,
                        'note_type' => $reply->note_type ?? 0,
                        'user_id' => $item->user_id,
                        'to_user_id' => $reply->to_user_id ?? 0,
                        'type' => $reply->type ?? 0,
                        'is_deleted' => $item->is_deleted,
                        'is_shield' => $item->is_shield,
                        'is_view' => $item->is_view,
                        'have_author_reply' => $item->have_author_reply,
                        'hot' => $item->hot,
                    ];
                    $res = IndexComment::getModel()->create($insert);
                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_comment` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check comment_id : {$item->comment_id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'comment_id');
        return 1;
    }

    /**
     * 索引修复 - 笔记
     * @return int
     */
    public function note()
    {
        $subMode = $this->_getNoteSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                // get index data
                $data = IndexNote::getModel()
                    ->where('note_id', $item->note_id)
                    ->first();
                if (empty($data)) {
                    $select = SysNoteLine::getSubModel(function (Builder $query) use($item) {
                        $query->where('note_id', $item->note_id);
                    })->first();
                    // insert data into table
                    $insert = [
                        'note_id' => $item->note_id,
                        'article_id' => $item->article_id,
                        'user_id' => $item->user_id,
                        'start_index' => $select->start_index ?? 0,
                        'end_index' => $select->end_index ?? 0,
                        'is_choice' => $item->is_choice,
                        'is_deleted' => $item->is_deleted,
                        'is_public' => $item->is_public,
                        'is_view' => $item->is_view,
                    ];
                    $res = IndexNote::getModel()->create($insert);
                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_note` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check note_id : {$item->note_id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'note_id');
        return 1;
    }

    /**
     * 索引修复 - 用户收藏夹
     * @return int
     */
    public function collectPackage()
    {
        $subMode = $this->_getCollectPackageSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                // get index data
                $data = IndexCollectPackage::getModel()
                    ->where('collect_package_id', $item->collect_package_id)
                    ->where('user_id', $item->user_id)
                    ->first();
                if (empty($data)) {
                    // insert data into table
                    $insert = [
                        'collect_package_id' => $item->collect_package_id,
                        'user_id' => $item->user_id,
                        'collect_package_name' => $item->name,
                        'is_default' => $item->is_default,
                        'is_deleted' => $item->is_deleted,
                        'is_public' => $item->is_public,
                    ];
                    $res = IndexCollectPackage::getModel()->create($insert);
                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_collect_package` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check collect_package_id : {$item->collect_package_id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'collect_package_id');
        return 1;
    }

    /**
     * 索引修复 - 搜索收藏
     * @return int
     */
    public function searchCollect()
    {
        $subMode = $this->_getUserCollectSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->collect_id;
                // get index data
                $data = IndexSearchCollect::getModel()
                    ->where('collect_id', $item->collect_id)
                    ->first();
                if (empty($data)) {
                    $targetId = $item->target_id;
                    $targetType = $item->target_type;

                    // 获取搜索内容
                    $content = '';
                    if (GlobalConst::TARGET_TYPE_ARTICLE == $targetType) {
                        // 查询文章标题
                        $content = SysArticle::getModel($targetId)->where('article_id', $targetId)->value('title');
                    } elseif (GlobalConst::TARGET_TYPE_NOTE == $targetType) {
                        // 查询笔记内容
                        $content = SysNoteContent::getModel($targetId)->where('note_id', $targetId)->value('content');
                    }
                    if (empty($content)) {
                        $info = "[$index/$finish] empty content! collect_id : {$id} - " . json_encode($item);
                        $this->warn($info);
                        continue;
                    }

                    // insert data into table
                    $insert = [
                        'collect_id' => $item->collect_id,
                        'user_id' => $item->user_id,
                        'search_title' => $content,
                        'is_deleted' => $item->is_deleted,
                    ];
                    $res = IndexSearchCollect::getModel()->create($insert);

                    // log info
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] insert data into `index_search_collect` [$res] - " . Json::encode($insert);
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check collect_id : {$id} .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'collect_id');
        return 1;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getArticleSubModel()
    {
        $subMode = SysArticle::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'article_id', 'author_id', 'spider_original_id', 'is_deleted', 'is_shield']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getCommentSubModel()
    {
        $subMode = SysComment::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'comment_id', 'user_id', 'target_id', 'target_type',
            'is_deleted', 'is_shield', 'is_view', 'have_author_reply', 'hot']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getDynamicSubModel()
    {
        $subMode = SysDynamic::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'dynamic_id', 'user_id', 'target_id', 'target_type', 'note_type',
            'type', 'is_deleted', 'is_view']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getNoteSubModel()
    {
        $subMode = SysNote::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'note_id', 'article_id', 'user_id',
            'type', 'is_choice', 'is_deleted', 'is_view', 'is_public', 'is_shield']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getCollectPackageSubModel()
    {
        $subMode = UserCollectPackage::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'collect_package_id', 'user_id', 'name', 'is_default', 'is_deleted', 'is_public']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getUserCollectSubModel()
    {
        $subMode = UserCollect::getSubModel(function (Builder $query) {
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'collect_id', 'user_id', 'target_id', 'target_type', 'is_deleted']);
        return $subMode;
    }


}
